package com.objectcarpentry.kaylee.ui.views;

import java.util.ArrayList;
import java.util.Collection;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter;
import org.eclipse.emf.edit.ui.dnd.LocalTransfer;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener;
import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import com.objectcarpentry.kaylee.AbstractPlaylist;
import com.objectcarpentry.kaylee.IPlayer;
import com.objectcarpentry.kaylee.IPlaylist;
import com.objectcarpentry.kaylee.KayleePackage;
import com.objectcarpentry.kaylee.KayleePlugin;
import com.objectcarpentry.kaylee.Library;
import com.objectcarpentry.kaylee.provider.KayleeItemProviderAdapterFactory;
import com.objectcarpentry.kaylee.provider.LibraryItemProvider;
import com.objectcarpentry.kaylee.ui.KayleeUIPlugin;

public class LibraryView extends ViewPart {

	public static final String ID = "com.objectcarpentry.kaylee.ui.views.library";
 
	protected TableViewer viewer;
	protected EditingSupport editingSupport;

	@Override
	public void createPartControl(Composite parent) {
		
		TableColumnLayout layout = new TableColumnLayout();
		parent.setLayout(layout);

		
		viewer = new TableViewer(parent);
		
		 KayleeItemProviderAdapterFactory factory = new KayleeItemProviderAdapterFactory(){
			@Override
			public Adapter createLibraryAdapter(){
				if (libraryItemProvider == null){
					libraryItemProvider = new LibraryItemProvider(this){
						@Override
						public Collection<? extends EStructuralFeature> getChildrenFeatures(Object object) {
							if (childrenFeatures == null) {
								childrenFeatures = new ArrayList<EStructuralFeature>();
								childrenFeatures.add(KayleePackage.Literals.LIBRARY__PLAYLISTS);
							}
							return childrenFeatures;
						}
					};
				}
				return libraryItemProvider;
			}
		};
		
		
		AdapterFactoryContentProvider contentProvider = new AdapterFactoryContentProvider(factory) {
			@Override
			public Object[] getElements(Object input){
				Object[] elements = super.getElements(input);
				Object[] elementsPlus = new Object[elements.length + 1];
				elementsPlus[0] = KayleePlugin.getDefault().getLibrary();
				System.arraycopy(elements, 0, elementsPlus, 1, elements.length);
				return elementsPlus;
			}
		};
		
		
		
		AdapterFactoryLabelProvider labelProvider = new AdapterFactoryLabelProvider(factory);
		
		
		TableViewerColumn column = new TableViewerColumn(viewer, SWT.LEFT);
		layout.setColumnData(column.getColumn(), new ColumnWeightData(4));
		
	
		viewer.getTable().setLinesVisible(false);
		viewer.getTable().setHeaderVisible(true);
		viewer.setContentProvider(contentProvider);
		viewer.setLabelProvider(labelProvider);
	
		
		createContextMenu();
		hookMouseListener();
		hookEditingSupport(column);
		hookSelectionListener();
		
		viewer.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK,
		      new Transfer [] { LocalTransfer.getInstance() },
		      new EditingDomainViewerDropAdapter(KayleePlugin.getDefault().getEditingDomain(), viewer));
		
		getSite().setSelectionProvider(viewer);	
		viewer.setInput(KayleePlugin.getDefault().getLibrary());
	}

	protected void hookEditingSupport(TableViewerColumn column) {
		
		
		column.setEditingSupport(new EditingSupport(viewer) {
			CellEditor editor = new TextCellEditor(viewer.getTable());

			@Override
			protected boolean canEdit(Object element) {
				return !(element instanceof Library);
			}

			@Override
			protected CellEditor getCellEditor(Object element) {
				return editor;
			}

			@Override
			protected Object getValue(Object element) {
				return ((IPlaylist) element).getName();
			}
			
			@Override
			protected void setValue(Object element, Object value) {
				EditingDomain domain = KayleePlugin.getDefault()
						.getEditingDomain();
				Command c = SetCommand.create(KayleePlugin.getDefault()
						.getEditingDomain(), element,
						KayleePackage.Literals.PLAYLIST__NAME, value);
				if (c.canExecute()) {
					domain.getCommandStack().execute(c);
				}
			}
		});
		
		
		viewer.getColumnViewerEditor().addEditorActivationListener(new ColumnViewerEditorActivationListener() {
			   public void beforeEditorActivated(ColumnViewerEditorActivationEvent event) {
				   if (event.eventType == ColumnViewerEditorActivationEvent.MOUSE_CLICK_SELECTION) {
			         if (!(event.sourceEvent instanceof MouseEvent)){
			            event.cancel = true;
			         } else {
			            MouseEvent m = (MouseEvent) event.sourceEvent;
			            if ((m.stateMask & SWT.ALT) == 0){
			               event.cancel = true;
			            }
			         }
			      } else if (event.eventType != ColumnViewerEditorActivationEvent.PROGRAMMATIC) {
			         event.cancel = true;
			      }
			   }
			   
			   public void afterEditorActivated(ColumnViewerEditorActivationEvent event) {}
			   public void afterEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {}
			   public void beforeEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {}
		});
		
		
	}

	private void createContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu");
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
		    public void menuAboutToShow(IMenuManager m) {
		       LibraryView.this.fillContextMenu(m);
		    }
		});
		
		Menu menu = menuMgr.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, viewer);
	}

	
	protected void fillContextMenu(IMenuManager m) {
		
	}

	protected void hookMouseListener(){
		viewer.addDoubleClickListener(new IDoubleClickListener(){

			@Override
			public void doubleClick(DoubleClickEvent event) {
				System.out.println("double.click");
				ISelection sel = event.getSelection();
				if (sel != null && sel instanceof IStructuredSelection){
					IStructuredSelection ssel = (IStructuredSelection) sel;
					AbstractPlaylist<?> first = (AbstractPlaylist<?>) ssel.getFirstElement();
					KayleeUIPlugin.getDefault().hookNavigationHandler(first);
					IPlayer player = KayleePlugin.getDefault().getPlayer();
					first.playOn(player, null);
				}
			}
		});
	}
	
	protected void hookSelectionListener(){
		viewer.addSelectionChangedListener(new ISelectionChangedListener(){

			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				IStructuredSelection sel = (IStructuredSelection) event.getSelection();
				if (!sel.isEmpty()){
					AbstractPlaylist<?> pl = (AbstractPlaylist<?>) sel.getFirstElement();
					KayleeUIPlugin.getDefault().setPlaylist(pl);
				}
			}
			
		});
	}
	
	@Override
	public void setFocus() {
		viewer.getControl().setFocus();
	}

	public void rename(ISelection selection){
		if (selection != null && !selection.isEmpty() && selection instanceof IStructuredSelection){
			Object first = ((IStructuredSelection) selection).getFirstElement();
			viewer.editElement(first, 0);			
		}
	}
	
}
